package com.lu.security.key;

import android.util.Base64;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.KeyGenerator;

/**
 * author: luqihua
 * date:2023/2/23
 * description: 公钥私钥创建者
 **/
public class KeyReader {
    public static PrivateKey getPrivateKey(String keyPKCS8) throws IOException, GeneralSecurityException {
        byte[] specs = decodePKCS8key(new ByteArrayInputStream(keyPKCS8.getBytes()));
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(specs);
        return KeyFactory.getInstance("RSA").generatePrivate(spec);
    }

    public static PublicKey getPublicKey(String keyPKCS8) throws IOException, GeneralSecurityException {
        byte[] specs = decodePKCS8key(new ByteArrayInputStream(keyPKCS8.getBytes()));
        X509EncodedKeySpec spec = new X509EncodedKeySpec(specs);
        return KeyFactory.getInstance("RSA").generatePublic(spec);
    }

    private static byte[] decodePKCS8key(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder sb = new StringBuilder();
        String buffer;
        while ((buffer = reader.readLine()) != null) {
            //舍弃-----BEGIN----  和   -----END----
            if (!buffer.contains("---")) {
                sb.append(buffer);
            }
        }
        reader.close();
        //需要进行base64转码

        return Base64.decode(sb.toString(), Base64.NO_WRAP);
    }


    /**
     * 从keystore中提取私钥
     *
     * @param alias
     * @param password
     * @param keyStream 存放keystore的流  可能是文件或者资源
     * @return
     */
    public static PrivateKey getPrivateKeyFromKeystore(String alias, String password, InputStream keyStream) throws IOException, GeneralSecurityException {
        /*从keystore提取秘钥*/
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(keyStream, password.toCharArray());
        keyStream.close();

        return (PrivateKey) keyStore.getKey(alias, password.toCharArray());
    }


    /**
     * 从xxxx.pk8文件中提取私钥
     *
     * @param pk8FileStream
     * @return
     */
    public static PrivateKey getPrivateKeyFromPK8(InputStream pk8FileStream) throws IOException, GeneralSecurityException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(pk8FileStream));
        StringBuilder sb = new StringBuilder();
        String buffer;
        while ((buffer = reader.readLine()) != null) {
            //舍弃-----BEGIN----  和   -----END----
            if (!buffer.contains("---")) {
                sb.append(buffer);
            }
        }
        reader.close();
        //需要进行base64转码

        byte[] specs = Base64.decode(sb.toString(), Base64.NO_WRAP);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(specs);
        return KeyFactory.getInstance("RSA").generatePrivate(spec);
    }


    /**
     * 从xxxx.pk8文件中提取私钥
     *
     * @param pk8FileStream
     * @return
     */
    public static PublicKey getPublicKeyFromPK8(InputStream pk8FileStream) throws IOException, GeneralSecurityException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(pk8FileStream));
        StringBuilder sb = new StringBuilder();
        String buffer;
        while ((buffer = reader.readLine()) != null) {
            //舍弃-----BEGIN----  和   -----END----
            if (!buffer.contains("---")) {
                sb.append(buffer);
            }
        }
        reader.close();
        //需要进行base64转码

        byte[] specs = Base64.decode(sb.toString(), Base64.NO_WRAP);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(specs);
        return KeyFactory.getInstance("RSA").generatePublic(spec);
    }

    /**
     * 根据特征值提取 privateKey
     *
     * @param N
     * @param d
     */
    public static PrivateKey getPrivateKeyFromNd(BigInteger N, BigInteger d) throws GeneralSecurityException {
        RSAPrivateKeySpec spec = new RSAPrivateKeySpec(N, d);
        return KeyFactory.getInstance("RSA").generatePrivate(spec);
    }

    /**
     * 从xxxxx.pem/cer/der/crt文件中提取公钥 他们都是x.509的证书格式
     *
     * @param keyStream
     */
    public static PublicKey getPublicKeyFromPem(InputStream keyStream) throws IOException, GeneralSecurityException {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate x509Certificate = (X509Certificate) certificateFactory.generateCertificate(keyStream);
        keyStream.close();
        return x509Certificate.getPublicKey();
    }

    /**
     * 根据特征值提取 PublicKey
     *
     * @param N
     * @param e
     */
    public static PublicKey getPublicKeyFromNe(BigInteger N, BigInteger e) throws GeneralSecurityException {
        /*根据N，e生成公钥*/
        RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(N, e);
        return KeyFactory.getInstance("RSA").generatePublic(publicKeySpec);
    }


    public static Key createAESKey() throws NoSuchAlgorithmException {
//        使用KeyGenerator生成key，参数与获取cipher对象的algorithm必须相同
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
//        AES 密钥长度可以是 128 位，192 位和 256 位
        keyGenerator.init(128);
        return keyGenerator.generateKey();
    }


    public static Key createDESKey() throws NoSuchAlgorithmException {
//        使用KeyGenerator生成key，参数与获取cipher对象的algorithm必须相同
        KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
        //DES的秘钥长度必须是56位
        keyGenerator.init(56);
        return keyGenerator.generateKey();
    }
}
